package presentation.windowsFackData;


import java.awt.Font ;
import java.rmi.RemoteException ;

import javax.swing.JButton ;
import javax.swing.JFrame ;
import javax.swing.JLabel ;
import javax.swing.JOptionPane ;
import javax.swing.SwingWorker ;
import javax.swing.WindowConstants ;

import presentation.UIUser ;
import presentation.windows.PanelObserver;
import presentation.windows.SharedUIData;
import util.Log ;
import util.NotFoundException ;
import util.Subsystem ;

import communication.Client ;

import domain.ForumLogic ;
import domain.user.Privilege ;
import domain.user.UnpermittedActionException ;



/**
 * The Class MainPanel creates the Main frame of the GUI and responsible for holding the . Base panel inside.
 * Also the main panel changes the inside panel according to the user pressing the buttons.
 */
public class MainPanelFake extends JFrame implements PanelObserver
{

	/** The forum. */
	private static ForumLogic forum ;

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 7928544302484474295L ;

	/** The admin mode button is the button for admin only for adding privileges to users. */
	private JButton adminModeButton ;

	/** The current panel is the panel that the main frame holds inside. */
	private BasePanelFake currentPanel ;

	/** The forum header. */
	private JLabel forumNameTextField ;

	/** The home button is the root page. */
	private JButton homeButton ;

	/** The login button. */
	private JButton loginButton ;

	/** The logout button, for logging out of the forum. becoming a guest and not a member */
	private JButton logoutButton ;

	/** The register button , for registration. */
	private JButton registerButton ;

	/** The search button. */
	private JButton searchButton ;

	/** The data that are shared between all panels and the Main frame . contain details about the user. */
	private SharedUIData sharedUIData ;
	private JLabel activeUsersLable;

	/** The edit profile button - for logged-in user **/
	private JButton editProfileButton ;

	private int activeGuests;
	private int activeMembers;


	/**
	 * transfer the forum to all inside panels. (for consequential of the forum)
	 *
	 * @return the forum
	 */
	public static ForumLogic getForum()
	{
		return MainPanelFake.forum ;
	}

	/**
	 * THE MAIN.
	 *
	 * @param args the arguments
	 */
	public static void main(final String[] args)
	{

		MainPanelFake mainPanel = null ;
		Log.setupDefaultConfig(); //start logger on this process
		try
		{
			mainPanel = new MainPanelFake() ;
		}
		catch (final Exception e)
		{
			e.printStackTrace();

			Log.getLogger(Subsystem.PRESENTATION_MODEL).severe(
				"Unknown bug from forum system : details: " + e.getStackTrace()) ;
			JOptionPane.showMessageDialog(mainPanel, "Error occure, please try again.. bye bye") ;
		}
	}

	/**
	 * Instantiates a new main panel.
	 *
	 */
	public MainPanelFake()
	{
		try
		{
			//MainPanel.forum = this.initLocalForum() ;
			MainPanelFake.forum = Client.instance("//localhost:2002/forumserver").getForum() ;
			this.sharedUIData = new SharedUIData(MainPanelFake.forum.registerGuest()) ;
			this.activeGuests = MainPanelFake.forum.getActiveGuests();
			this.activeMembers = MainPanelFake.forum.getActiveMemberNames().size();
			this.initGUI() ;
		}
		catch (final RemoteException e)
		{
			Log.getLogger(Subsystem.PRESENTATION_MODEL).info("Remote problems thrown in Main frame: "+e.getMessage()) ;
			JOptionPane.showMessageDialog(MainPanelFake.this, "Communication problems, please try again",
				"error occured", JOptionPane.ERROR_MESSAGE) ;
		}
		catch (final NotFoundException e)
		{
			// panel is not created properly
			JOptionPane.showMessageDialog(MainPanelFake.this, "Problem eith loading the panel, please try again",
				"error occured", JOptionPane.ERROR_MESSAGE) ;
		}

	}

	/**
	 * @see java.awt.Window#dispose()
	 */
	@Override
	public void dispose()
	{
		super.dispose() ;
		try
		{
			MainPanelFake.forum.exitUser(this.sharedUIData.getUser().getId()) ;
		}
		catch (RemoteException e)
		{
			Log.getLogger(Subsystem.PRESENTATION_MODEL).info("cannot exit user") ;
		}
		System.exit(0); //exit application (as EXIT_ON_CLOSE does) - to close all open frames
	}

	/**
	 * @see presentation.windows.PanelObserver#updateActivePanel()
	 */
	@Override
	public void updateActivePanel()
	{
		this.homeButtonHandler(); //simulate the press of "home" button
	}


	/**
	 * Admin mode button handler pressed only by the admin. this button appears only when the admin login to
	 * the forum. The inside panel removes the current panel and upload a new ladmin panel
	 */
	private void adminModeButtonHandler()
	{
		this.updateActiveUsers();
		this.currentPanel.closeOpenSubFrames();
		this.remove(this.currentPanel) ;
		this.currentPanel = new AdminFakePanel(this.sharedUIData) ;
		this.currentPanel.attachObserver(this);
		this.currentPanel.makeVisible() ;
		this.getContentPane().add(this.currentPanel) ;
		this.currentPanel.setBounds(120, 110, 735, 566) ;
		this.pack();
		this.setVisible(true) ;
	}

	/**
	 * Register button handler pressed when the user want to edit his profile. The inside panel removes the
	 * current panel and upload a new edit profile panel.
	 */
	private void editProfileButtonHandler()
	{

		this.updateActiveUsers();
		this.currentPanel.closeOpenSubFrames();
		this.remove(this.currentPanel) ;
		this.currentPanel = new EditProfileFakePanel(this.sharedUIData) ;
		this.currentPanel.attachObserver(this);
		this.currentPanel.makeVisible() ;
		this.getContentPane().add(this.currentPanel) ;
		this.currentPanel.setBounds(120, 110, 735, 566) ;
		this.pack();
		this.setVisible(true) ;

	}

	/**
	 * Home button handler press when the user want to return the directories page. The inside panel removes
	 * the current panel and upload a new directories panel
	 */
	private void homeButtonHandler()
	{
		this.updateActiveUsers();
		this.currentPanel.closeOpenSubFrames();
		this.remove(this.currentPanel) ;

		if (this.sharedUIData.isLoggedIn() == true)
		{
			this.logoutButton.setVisible(true) ;
			this.editProfileButton.setVisible(true) ;
			this.loginButton.setEnabled(false);
		}
		if (this.sharedUIData.getUser().isAllowed(Privilege.GIVE_PERMISSION))
		{
			this.adminModeButton.setVisible(true) ;
		}

		new SwingWorker<Void,Void>(){
			@SuppressWarnings("synthetic-access")
			@Override
			protected Void doInBackground(){
				try
				{
					MainPanelFake.this.currentPanel = new ViewDirectoryFakePanel(MainPanelFake.this.sharedUIData) ;
					MainPanelFake.this.getContentPane().add(MainPanelFake.this.currentPanel) ;
					MainPanelFake.this.currentPanel.setBounds(120, 110, 735, 566) ;
					MainPanelFake.this.pack();
					MainPanelFake.this.setVisible(true) ;
				}
				catch (final RemoteException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("Remote problems thrown in Main frame: "+e.getMessage()) ;
					JOptionPane.showMessageDialog(MainPanelFake.this, "Communication problems, please try again",
						"error occured", JOptionPane.ERROR_MESSAGE) ;
				}
				catch (final NotFoundException e)
				{
					// panel is not created properly
					JOptionPane.showMessageDialog(MainPanelFake.this, "Problem eith loading the panel, please try again",
						"error occured", JOptionPane.ERROR_MESSAGE) ;
				}
				return null;
			}
			@Override
			protected void done(){/*nothing to do here */}
		}.execute();
	}


	/**
	 * Initiates all Gui, buttons and root page.
	 *
	 * @throws RemoteException the remote exception
	 * @throws NotFoundException the not found exception
	 */
	private void initGUI() throws RemoteException, NotFoundException
	{
		this.setPreferredSize(new java.awt.Dimension(950, 768)) ;
		this.setMaximumSize(new java.awt.Dimension(950, 768));
		this.setTitle("RIVHR Forum");
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE) ;
		this.getContentPane().setLayout(null) ;
		{
			this.currentPanel = new ViewDirectoryFakePanel(this.sharedUIData) ;
			this.getContentPane().add(this.currentPanel) ;
			this.currentPanel.setBounds(90, 100, 735, 566) ;
		}
		{
			this.forumNameTextField = new JLabel() ;
			this.getContentPane().add(this.forumNameTextField) ;
			this.forumNameTextField.setText("R I V H R Forum") ;
			this.forumNameTextField.setFont(new Font("Francais", 1, 28)) ;
			this.forumNameTextField.setBounds(329, 12, 257, 27) ;
		}
		{
			this.homeButton = new JButton() ;
			this.getContentPane().add(this.homeButton) ;
			this.homeButton.setText("Home") ;
			this.homeButton.setBounds(66, 60, 87, 29) ;
		}
		{
			this.loginButton = new JButton() ;
			this.getContentPane().add(this.loginButton) ;
			this.loginButton.setText("Login") ;
			this.loginButton.setBounds(182, 60, 83, 29) ;
		}
		{
			this.logoutButton = new JButton() ;
			this.getContentPane().add(this.logoutButton) ;
			this.logoutButton.setText("Logout") ;
			this.logoutButton.setBounds(659, 60, 86, 29) ;
			this.logoutButton.setVisible(false) ;
		}
		{
			this.registerButton = new JButton() ;
			this.getContentPane().add(this.registerButton) ;
			this.registerButton.setText("Register") ;
			this.registerButton.setBounds(411, 60, 92, 29) ;
		}
		{
			this.editProfileButton = new JButton() ;
			this.getContentPane().add(this.editProfileButton) ;
			this.editProfileButton.setText("Edit Profile") ;
			this.editProfileButton.setBounds(534, 60, 97, 29) ;
			this.editProfileButton.setVisible(false);
		}
		{
			this.searchButton = new JButton() ;
			this.getContentPane().add(this.searchButton) ;
			this.searchButton.setText("Search") ;
			this.searchButton.setBounds(293, 60, 89, 29) ;
		}
		{
			this.adminModeButton = new JButton() ;
			this.getContentPane().add(this.adminModeButton) ;
			this.adminModeButton.setText("Admin Mode") ;
			this.adminModeButton.setBounds(774, 60, 113, 29) ;
			this.adminModeButton.setVisible(false) ;
		}

		this.activeUsersLable = new JLabel();
		this.getContentPane().add(this.activeUsersLable);
		this.activeUsersLable.setText("Currently there are "+this.activeGuests+" guests and "+this.activeMembers+" registered users connected to the forum");
		this.activeUsersLable.setBounds(120, 688, 735, 39);
		this.activeUsersLable.setFont(new java.awt.Font("Tahoma",0,14));

		this.pack() ;
		this.setVisible(true) ;

		if (this.sharedUIData.isLoggedIn() == true)
		{
			this.logoutButton.setVisible(true) ;
		}

		if (this.sharedUIData.getUser().isAllowed(Privilege.GIVE_PERMISSION))
		{
			this.adminModeButton.setVisible(true) ;
		}

		// set button handlers:
		this.homeButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				MainPanelFake.this.homeButtonHandler() ;
			}
		}) ;

		this.loginButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				MainPanelFake.this.loginButtonHandler() ;
			}
		}) ;

		this.logoutButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				new SwingWorker<Void,Void>(){
	     			@Override
	     			protected Void doInBackground(){
	     				MainPanelFake.this.logoutButtonHandler() ;
	     				return null;
	     			}
	     			@Override
	    			protected void done() { /* there is nothing to do here .. */ }
	    		}.execute();
			}
		}) ;

		this.registerButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				MainPanelFake.this.registerButtonHandler() ;
			}
		}) ;

		this.editProfileButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				new SwingWorker<Void,Void>(){
	     			@Override
	     			protected Void doInBackground(){
	     				MainPanelFake.this.editProfileButtonHandler() ;
	     				return null;
	     			}
	     			@Override
	    			protected void done() { /* there is nothing to do here .. */ }
	    		}.execute();
			}
		}) ;

		this.searchButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				MainPanelFake.this.searchButtonHandler() ;
			}
		}) ;

		this.adminModeButton.addActionListener(new java.awt.event.ActionListener()
		{
			@SuppressWarnings("synthetic-access")
			public void actionPerformed(@SuppressWarnings("unused") final java.awt.event.ActionEvent evt)
			{
				MainPanelFake.this.adminModeButtonHandler() ;
			}
		}) ;

	}


	/**
	 * Login button handler press when the user want to login the forum. The inside panel removes the current
	 * panel and upload a new login panel
	 */
	private void loginButtonHandler()
	{
		this.updateActiveUsers();
		this.currentPanel.closeOpenSubFrames();
		this.remove(this.currentPanel) ;
		this.currentPanel = new LoginFakePanel(this.sharedUIData) ;
		this.currentPanel.attachObserver(this);
		this.getContentPane().add(this.currentPanel) ;
		this.currentPanel.setBounds(120, 110, 735, 566) ;
		this.pack();
		this.setVisible(true) ;
	}

	/**
	 * Logout button handler pressed when the user wants to logout from the system. This button appears only
	 * after the user logged in to the forum
	 */
	private void logoutButtonHandler()
	{
		try
		{
			final long userId = this.sharedUIData.getUser().getId() ;
			MainPanelFake.forum.logout(userId) ;
			final UIUser user = MainPanelFake.forum.registerGuest() ;
			this.sharedUIData.setUser(user) ;
			this.sharedUIData.setLoggedIn(false) ;

			if (this.sharedUIData.isLoggedIn() == false)
			{
				this.logoutButton.setVisible(false) ;
				this.editProfileButton.setVisible(false) ;
				this.loginButton.setEnabled(true);
			}
			if (!this.sharedUIData.getUser().isAllowed(Privilege.GIVE_PERMISSION))
			{
				this.adminModeButton.setVisible(false) ;
			}

			//change or refresh window, depending the panel type
			if(this.currentPanel instanceof EditProfileFakePanel)
			{
				this.homeButtonHandler();
			}
			else
			{
				this.updateActiveUsers();
				this.currentPanel.makeVisible() ;
			}
		}
		catch (final RemoteException e)
		{
			Log.getLogger(Subsystem.PRESENTATION_MODEL).info("Remote problems thrown in Main frame: "+e.getMessage()) ;
			JOptionPane.showMessageDialog(MainPanelFake.this, "Communication problems, please try again",
				"error occured", JOptionPane.ERROR_MESSAGE) ;
		}
		catch (final NotFoundException e)
		{
			// this NOT supposed to occur because logout button is presented only after login, still systems
			// problems
			Log.getLogger(Subsystem.PRESENTATION_MODEL).severe(
				"The user id does not found while trying to logout " + e.getStackTrace()) ;
		}
		catch (UnpermittedActionException e)
		{
			Log.getLogger(Subsystem.PRESENTATION_MODEL).info("Cannot logout: "+e.getMessage()) ;
			JOptionPane.showMessageDialog(MainPanelFake.this, "You are not allowed to logout",
				"error occured", JOptionPane.ERROR_MESSAGE) ;
		}
	}

	/**
	 * Register button handler pressed when the user want to register the forum. The inside panel removes the
	 * current panel and upload a new register panel.
	 */
	private void registerButtonHandler()
	{
		this.updateActiveUsers();
		this.currentPanel.closeOpenSubFrames();
		this.remove(this.currentPanel) ;
		this.currentPanel = new RegisterFakePanel(this.sharedUIData) ;
		this.currentPanel.attachObserver(this);
		this.currentPanel.makeVisible() ;
		this.getContentPane().add(this.currentPanel) ;
		this.currentPanel.setBounds(120, 110, 735, 566) ;
		this.pack();
		this.setVisible(true) ;
	}

	/**
	 * Search button handler.
	 */
	private void searchButtonHandler()
	{
		this.updateActiveUsers();
		this.currentPanel.closeOpenSubFrames();
		this.remove(this.currentPanel) ;
		this.currentPanel = new SearchFakePanel(this.sharedUIData) ;
		this.currentPanel.makeVisible() ;
		this.getContentPane().add(this.currentPanel) ;
		this.currentPanel.setBounds(120, 110, 735, 566) ;
		this.pack();
		this.setSize(950, 768);
		this.setVisible(true) ;
	}

	private void updateActiveUsers(){

		new SwingWorker<Void,Void>(){

			@SuppressWarnings("synthetic-access")
			@Override
			protected Void doInBackground(){
				try
				{
					MainPanelFake.this.activeGuests = MainPanelFake.forum.getActiveGuests();
				}
				catch(RemoteException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("Remote problems thrown when trying to update active guests: "+e.getMessage()) ;
				}
				try
				{
					MainPanelFake.this.activeMembers = MainPanelFake.forum.getActiveMemberNames().size();
				}
				catch(RemoteException e)
				{
					Log.getLogger(Subsystem.PRESENTATION_MODEL).info("Remote problems thrown when trying to update active members: "+e.getMessage()) ;
				}
				return null;
			}
			@SuppressWarnings("synthetic-access")
			@Override
			protected void done(){
				MainPanelFake.this.activeUsersLable.setText("Currently there are "+MainPanelFake.this.activeGuests+" guests and "+MainPanelFake.this.activeMembers+" registered users connected to the forum");
			}
		}.execute();
	}

}

